package dao

import (
	"fmt"
	"gorm.io/gorm"
	"strings"
	"time"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/helper/resphelper/placeresp"
	"yundian/internel/app/models/users"
	"yundian/internel/app/models/wifimodel"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
	"yundian/internel/pkg/utils"
)

type WifiDao struct {

}

func NewWifiDao() *WifiDao {
	return &WifiDao{}
}

// 单价列表
func (d *WifiDao) AdSettingListDao(baseListReq *request.BaseListReq) *dingo.ErrorWrap {

	var (
		lst    []wifimodel.WifiAdSetting
		count  int64
		limit  = baseListReq.PageSize
		offset = baseListReq.PageSize * (baseListReq.PageNo - 1)
	)
	db := global.Orm.Table("wifi_ad_setting").Order("date_str DESC")
	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)
	return dingo.ErrorIf(db.Error, lst, count)
}

// 单价保存
func (d *WifiDao) WithdrawalSettingSaveDao(param *wifimodel.WifiAdSetting) *dingo.ErrorWrap {

	db := global.Orm.Table("wifi_ad_setting")
	db.Create(&param)
	if db.Error != nil {
		return dingo.ErrorIf(db.Error, false)
	}
	return dingo.ErrorIf(db.Error, true)
}

// GetWifiServiceLogList  服务点击日志列表
func (d *WifiDao) GetWifiServiceLogList(param *request.ServiceClickLogsListReq) *dingo.ErrorWrap {
	var (
		lst    []wifimodel.AdServiceModel
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)
	field := `lsl.*,p.province,p.city,p.county,p.address,REPLACE(m.phone, SUBSTR(phone,4,4), '****') as phone`
	db := global.Orm.Table("wifi_service_log lsl").
		Select(field).
		Joins("LEFT JOIN places p ON lsl.place_id = p.id").
		Joins("LEFT JOIN members m ON lsl.member_id = m.id")
	if param.PlaceName != "" { db.Where("lsl.place_name like ?", fmt.Sprint("%", param.PlaceName, "%")) }
	if param.PlaceId > 0 { db.Where("lsl.place_id = ?", param.PlaceId) }
	if param.ServiceType > 0 { db.Where("lsl.service_type = ?", param.ServiceType) }
	if param.ServiceDesc != "" { db.Where("lsl.service_desc like ?", fmt.Sprint("%", param.ServiceDesc, "%")) }
	db.Order("lsl.id desc")
	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)
	return dingo.ErrorIf(db.Error, lst, count)
}

// 获取单价详情
func (d *WifiDao) GetAdSettingInfo(dateStr string) *dingo.ErrorWrap {
	m := &wifimodel.WifiAdSetting{}
	db := global.Orm.Table("wifi_ad_setting").Where("date_str = ?", dateStr).Find(m)

	return dingo.ErrorIf(db.Error, m)
}

// 获取uv生成收益数
func (d *WifiDao) CountAdIncomeLog(dateStr, openid string) *dingo.ErrorWrap {
	var count int64
	sql := "SELECT count(1) FROM wifi_ad_income_log WHERE openid = ? and date_str = ?"
	db := global.Orm.Debug().Raw(sql, openid, dateStr).Find(&count)
	return dingo.ErrorIf(db.Error, count)
}

func (d *WifiDao) CountAdOrder(dateStr, openid, appId string) *dingo.ErrorWrap {
	var count int64
	sql := "SELECT count(1) FROM wifi_ad_orders WHERE openid = ? and date_str = ? and appid = ?"
	db := global.Orm.Debug().Raw(sql, openid, dateStr, appId).Find(&count)
	return dingo.ErrorIf(db.Error, count)
}

func (d *WifiDao) GetWifiUserIncomeByDateStr(userId int) *dingo.ErrorWrap {
	dateStr := time.Now().Format("2006-01-02")
	m := &wifimodel.AdIncomeList{}
	sql := `SELECT SUM(ad_price) ad_price, user_id, date_str FROM wifi_ad_income_log WHERE user_id = ? and date_str = ?`
	db := global.Orm.Debug().Raw(sql, userId, dateStr).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

func (d *WifiDao) GetLastAdOrder(openid, appId string) *dingo.ErrorWrap {
	orderInfo := &wifimodel.AdOrderModel{}
	sql := "SELECT * FROM wifi_ad_orders WHERE openid = ? and appid = ? ORDER BY id DESC LIMIT 1"
	db := global.Orm.Debug().Raw(sql, openid, appId).Find(&orderInfo)
	return dingo.ErrorIf(db.Error, orderInfo)
}

// 新增广告收益
func (d *WifiDao) InsertAdIncome(tx *gorm.DB, m *wifimodel.AdIncomeModel) *dingo.ErrorWrap {
	db := tx.Table("wifi_ad_income_log").Create(m)
	return dingo.ErrorIf(db.Error, true)
}

// 新增广告订单
func (d *WifiDao) InsertAdOrder(tx *gorm.DB, m *wifimodel.AdOrderModel) *dingo.ErrorWrap {
	db := tx.Table("wifi_ad_orders").Create(m)
	return dingo.ErrorIf(db.Error, true)
}

// 获取已提现金额
func (d *WifiDao) GetCashLogByUserId(userId int) *dingo.ErrorWrap {
	var total int64
	sql := `select IFNULL(SUM(money),0) as total from 
wifi_ad_cash_log WHERE user_id = ? and state = 2`
	db := global.Orm.Debug().Raw(sql, userId).Find(&total)
	return dingo.ErrorIf(db.Error, total)
}

// 获取用户分红金额
func (d *WifiDao) GetDividendsMoneyByUserId(userId int) *dingo.ErrorWrap {
	var total float64
	sql := "SELECT IFNULL(SUM(ad_price),0) as total FROM wifi_ad_income_log WHERE user_id = ?"
	db := global.Orm.Debug().Raw(sql, userId).Find(&total)
	return dingo.ErrorIf(db.Error, total)
}

// 获取未入帐金额
func (d *WifiDao) GetUnCashMoneyByUserId(userId int, dateStr string) *dingo.ErrorWrap {
	var total float64
	sql := `SELECT IFNULL(SUM(ad_price),0) as total FROM wifi_ad_income_log WHERE user_id = ? 
	and date_str > ?`
	db := global.Orm.Debug().Raw(sql, userId, dateStr).Find(&total)
	return dingo.ErrorIf(db.Error, total)
}

// 获取已入帐金额
func (d *WifiDao) GetCashMoneyByUserId(userId int, dateStr string) *dingo.ErrorWrap {
	var total float64
	sql := `SELECT IFNULL(SUM(ad_price),0) as total FROM wifi_ad_income_log WHERE user_id = ? 
	and date_str <= ?`
	db := global.Orm.Debug().Raw(sql, userId, dateStr).Find(&total)
	return dingo.ErrorIf(db.Error, total)
}

// 获取提现列表
func (dao *WifiDao) GetCashList(param *request.CashListReq) *dingo.ErrorWrap {

	var (
		lst    []*wifimodel.AdCashLogModel
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)

	db := global.Orm.Debug().Table("wifi_ad_cash_log w").
		Select("w.*,u.phone,u.name,u.wx_income_qrcode").
		Joins("left join users u on u.id = w.user_id")

	if param.UserId != 2 {
		db.Where("w.user_id=?", param.UserId)
	}
	if param.Name != "" {
		db.Where("u.name like ?", fmt.Sprint("%", param.Name, "%"))
	} // 申请人姓名
	if param.Phone != "" {
		db.Where("u.phone = ?", param.Phone)
	} // 手机号码
	if param.Status > 0 {
		db.Where("w.state = ?", param.Status)
	}

	// 时间查询
	if param.BeginTime != "" {
		beginTime := strings.Split(param.BeginTime, ",")
		db.Where("w.create_at >= ? and w.create_at<= ?", beginTime[0], beginTime[1])
	}

	// 排序
	if param.SortField != "" && param.SortOrder == "ascend" {
		db.Order(fmt.Sprintf("w.%s asc", utils.String(param.SortField).SnakeCase()))
	}
	if param.SortField != "" && param.SortOrder == "descend" {
		db.Order(fmt.Sprintf("w.%s desc", utils.String(param.SortField).SnakeCase()))
	}
	if param.SortField == "" {
		db.Order("w.create_at desc")
	}

	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, lst, count)
}

// 获取收益明细
func (d *WifiDao) GetIncomeList(param *request.IncomeListReq) *dingo.ErrorWrap {

	var (
		lst    []wifimodel.AdIncomeList
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)

	db := global.Orm.Table("wifi_ad_income_log").
		Select("SUM(ad_price) as ad_price, date_str, user_id").
		Where("user_id = ?", param.UserId).
		Group("date_str")
	//if param.UserId > 0 {
	//	db.Where("user_id = ?", param.UserId)
	//}
	//
	db.Order("date_str desc")

	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, lst, count)
}

// 获取提现记录
func (d *WifiDao) GetCashLogByInfo(userId int) *dingo.ErrorWrap {
	cashLogModel := wifimodel.AdCashLogModel{}
	sql := `select * from 
wifi_ad_cash_log WHERE user_id = ? and state = 1`
	db := global.Orm.Debug().Raw(sql, userId).Find(&cashLogModel)
	return dingo.ErrorIf(db.Error, cashLogModel)
}

// 获取团队列表
func (d *WifiDao) GetUserListByParentId(parentId int, param *request.BaseListReq, platform string) *dingo.ErrorWrap {

	var (
		lst    []*wifimodel.WifiUserInfo
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)
	field := `u.id,u.id user_id,IFNULL(wu.is_admin,u.is_admin)is_admin,IFNULL(wu.profit_proportion,
	u.profit_proportion)profit_proportion,IFNULL(wu.is_divinds,u.is_divinds)is_divinds,u.parent_id,u.name,u.user_name,u.phone,u.nick_name`
	db := global.Orm.Debug().
		Table("users u").Select(field).
		Joins("LEFT JOIN wifi_user wu ON u.id = wu.user_id").
		Where("u.parent_id = ?", parentId).
		Where("u.is_delete = 0").
		Where("FIND_IN_SET(?, u.platform)", platform)

	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, lst, count)
}

func (d *WifiDao) GetUserListByParentIdAndIsAdmin(parentId int, isAdmin uint8, param *request.UserList) *dingo.ErrorWrap {

	var (
		lst    []*users.WifiUserListWithIncome
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)
	field := `u.*, ad.money, uc.user_count`
	db := global.Orm.Debug().
		Table("users u").Select(field).
		Joins("LEFT JOIN (SELECT SUM(ad_price) as money,user_id FROM wifi_ad_income_log GROUP BY user_id) ad ON u.id = ad.user_id").
		Joins("LEFT JOIN (SELECT count(1) as user_count,parent_id FROM users WHERE is_admin = 3 GROUP BY parent_id) as uc ON ad.user_id = uc.parent_id").
		Where("u.parent_id = ?", parentId).
		Where("u.is_admin = ?", isAdmin).Order("ad.money desc")

	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, lst, count)
}

// 获取团队数量
func  (d *WifiDao) GetUserCountByParentId(parentId int, isAdmin uint8) *dingo.ErrorWrap {
	var count int64
	db := global.Orm.Table("users").
		Where("parent_id = ?", parentId)
	if isAdmin > 0 {
		db.Where("is_admin = ?", isAdmin)
	}
	db.Count(&count)
	return dingo.ErrorIf(db.Error, count)
}

// FetchWifiDeviceList 获取设备列表
func (d *WifiDao) FetchWifiDeviceList(param *request.StewardDeviceListReq) *dingo.ErrorWrap {
	var (
		lst    []*request.StewardDeviceListRes
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)

	fields := `d.device_sn,d.place_id,p.place_name,r.wifi_name,r.wifi_password`
	db := global.Orm.Table("devices d").Select(fields)
	db.Joins("LEFT JOIN places p ON d.place_id=p.id")
	db.Joins("LEFT JOIN room r ON d.place_id=r.place_id AND d.room=r.room")
	if param.IsAdmin == 3 { // 商户下的设备WIFI
		db.Where("p.user_id = ?", param.LoginUserId)
	}
	if param.IsAdmin == 9 { // 拓展员下的设备WIFI
		db.Joins("LEFT JOIN users u ON p.user_id = u.id")
		db.Where("u.parent_id = ?", param.LoginUserId)
	}
	if param.IsAdmin == 8 { // 团长下的设备WIFI
		db.Where("d.agent_user_id = ?", param.LoginUserId)
	}

	if param.DeviceSn != "" {
		db.Where("d.device_sn=?", param.DeviceSn)
	}

	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)
	return dingo.ErrorIf(db.Error, lst, count)
}

func (d *WifiDao) GetWifiPlaceList(param *request.GetWifiPlaceListReq) *dingo.ErrorWrap {
	var (
		lst    []*placeresp.WifiPlaceListResp
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)

	db := global.Orm.Table("places p").
		Select("p.*, u.name, u.phone, d.qrcode_count").
		Joins("LEFT JOIN users u ON p.user_id = u.id").
		Joins("LEFT JOIN (SELECT count(1) as qrcode_count, place_id FROM devices GROUP BY place_id) as d ON d.place_id = p.id")

	if param.IsAdmin == 0 { // 个人 - 直营
		db.Where("p.user_id = ?", param.LoginUserId)
	} else {
		uList := NewUserDao().QueryChildUserIds(param.LoginUserId).Unwrap().([]int)
		pList := NewUserDao().GetPlacesIds(param.LoginUserId, uList).Unwrap().([]int)
		db.Where("p.id IN ?", pList)
	}

	if param.PlaceName != "" {
		PlaceStrSql := "%" + param.PlaceName + "%"
		db.Where("p.place_name LIKE ?", PlaceStrSql)
	}

	db.Limit(limit).Offset(offset).Find(&lst).Offset(-1).Limit(-1).Count(&count)
	return dingo.ErrorIf(db.Error, lst, count)
}


func (d *WifiDao) GetWifiCashLogList(param *request.WifiCashLogListReq) *dingo.ErrorWrap {
	var (
		lst    []wifimodel.AdCashLogModelWithUser
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)
	field := `wacl.*, u.phone, u.user_name, u.name, u.nick_name`
	db := global.Orm.Table("wifi_ad_cash_log wacl").
		Select(field).
		Joins("LEFT JOIN users u ON wacl.user_id = u.id")
	if param.Phone != "" { db.Where("u..phone = ?", param.Phone) }

	db.Order("wacl.id desc")
	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)
	return dingo.ErrorIf(db.Error, lst, count)
}
